/* eslint-disable */

import { getStorageValue, setStorageValue, removeStorageValue } from '/src/utils'
import { funcSortColumns } from '/src/utils'
import { ref, unref, reactive, h, watch } from 'vue'
import { post } from "/src/api/index";
import { ElMessage } from '/src/utils'
import { batchUpdateValue } from '/src/utils'
import { ElMessageBox } from 'element-plus'
import { ArrowLeft, ArrowRight } from '@element-plus/icons-vue'
import { getSelection } from '/src/utils/index'

import dayjs from 'dayjs'

export function fixBlankFileds(obj, obj_ori, columns) {
  let objOri = {...(obj_ori || {})}
  for (let p in objOri) {
    if (typeof(objOri[p]) === 'string') {
      objOri[p] = objOri[p].trim()
    }
  }

  let objOut = {...obj}
  let count = 0
  for (let p in objOut) {
    if (p == 'updated_at'
      || p == 'updatedby'
      || p == '#'
    ) {
      delete objOut[p]
      continue;
    }
    let column = null
    if (columns) {
      column = columns.find(item => item.prop === p)
    }
    if (column && column.discard) {
      delete objOut[p]
      continue;
    }
    if (typeof(objOut[p]) === 'string') {
      objOut[p] = objOut[p].trim()
    }
    if (column && column.force_update) {

    } else {
      if (objOut[p] instanceof Array && objOut[p].length == 0) {
        if (!(p in objOri)) {
          delete objOut[p]
          continue;
        }
        if (objOri[p] instanceof Array && objOri[p].length == 0) {
          delete objOut[p]
          continue;
        }
      }
      if (objOut[p] === '' || objOut[p] === null || objOut[p] === undefined) {
        if (!(p in objOri)) {
          delete objOut[p]
          continue;
        }
        if (objOri[p] === '' || objOri[p] === null || objOri[p] === undefined) {
          delete objOut[p]
          continue
        }
      }
      if (p in objOri && objOut[p] === objOri[p]) {
        delete objOut[p]
        continue;
      }
      if (column && objOut[p] === null && (column.type == 'datetime' || column.type == 'date' || column.type == 'year')) {
        if (!('query_options_setnull' in objOut)) {
          objOut.query_options_setnull = {}
        }
        objOut.query_options_setnull[p] = 1
        delete objOut[p]
      } else  if (column && objOut[p] === '') {
        if (column.type == 'number' || column.type == 'select') {
          if (!('query_options_setnull' in objOut)) {
            objOut.query_options_setnull = {}
          }
          objOut.query_options_setnull[p] = 1
          delete objOut[p]
        }
      }
    }
    count++
  }
  if (count == 0) {
    return null;
  }

  return objOut
}

export function init(self) {
  self.fixBlankFileds = fixBlankFileds
  self.buttons = ref([])
  self.insertLineColunmn = () => {
    // self.columns.value.splice(0, 0, {
    //   prop: '#',
    //   label: '#',
    //   type: 'index',
    //   fixed: true,
    //   width: 60,
    //   sortable: false,
    //   discard_export: true,
    // })
  }
  self.insertLineColunmn();

  //不导出id
  {
    const column = unref(self.columns).find(e => e.prop == 'id')
    if (column) {
      column.discard_export = true
    }
  }

  //设置列表的remark字段宽度
  {
    const column = unref(self.columns).find(e => e.prop == 'remark')
    if (column) {
      column.width = 300
    }
  }

  //设置编辑form的remark字段类型
  {
    const column = unref(self.editColumns).find(e => e.prop == 'remark')
    if (column) {
      column.type = 'textarea'
    }
  }

  const customButtons = (self.custom || {}).buttons || []
  const customColumns = (self.custom || {}).columns || []
  const customEditColumns = (self.custom || {}).editColumns || []
  const customqueryColumns = (self.custom || {}).queryColumns || []
  const customRemoteConfig = (self.custom || {}).remoteConfig || {}

  // console.log('module', self.module.value)

  self.columns.value = funcSortColumns(self.columns.value, customColumns, 'columns')
  self.editColumns.value = funcSortColumns(self.editColumns.value, customEditColumns, 'editColumns')
  self.queryColumns.value = funcSortColumns(self.queryColumns.value, customqueryColumns, 'queryColumns')

  self.editColumns.value.forEach( column => {
    if (column.type == 'double' && !column.onchange) {
      column.onchange =  (param) => {
        let {mode, form, column, columns, get_remote_list, set_query_storage} = param
        if (form[column.prop] !== null && form[column.prop] !== undefined) {
          try {
            let v = parseFloat(form[column.prop])
            if (isNaN(v)) {
              form[column.prop] = ''
            } else {
              if (v+'' != form[column.prop]) {
                form[column.prop] = v+''
              }
            }
          }catch(ex) {
            form[column.prop] = ''
          }
        }
      }
    }
  })

  for(let p in customRemoteConfig) {
    let item = customRemoteConfig[p]
    let oriItem = self.remoteConfig.value[p]
    if (oriItem) {
      for(let p in item) {
        oriItem[p] = item[p]
      }
    } else {
      self.remoteConfig.value[p] = item
    }
  }

  customButtons.forEach ( item => {
    let oriItem = self.buttons.value.find( ele => ele.prop == item.prop)
    if (oriItem) {
      for(let p in item) {
        oriItem[p] = item[p]
      }
    } else {
      self.buttons.value.push(item)
    }
  })

  let queryInfoList = self.queryColumns.value

  let pageSize = getStorageValue('pageSize')
  if (!pageSize) {
    pageSize = 10
  } else {
    pageSize = parseInt(pageSize)
  }
  queryInfoList = [
    ...queryInfoList,
    {prop: 'pageNo', default: 1, result_value_type: 'int'},
    {prop: 'pageSize', default: pageSize, result_value_type: 'int'}
  ]
  let workspaceName = getStorageValue('workspace_name')

  self.loadSort = () => {
    let sortInfo = getStorageValue('order_'+self.name.value)
    if (!sortInfo || !(sortInfo instanceof Array) || !sortInfo.length) {
      if(self.custom){
        let orderIndex = 0
        sortInfo = unref(unref(self.custom).columns).filter(ele => ele.order_ori).map(ele => {
          return {
            prop: ele.prop,
            order: ele.order_ori,
            orderIndex: ++orderIndex,
          }
        })
      }
      
    }
    if (sortInfo && sortInfo instanceof Array && sortInfo.length > 0) {
      unref(self.columns).forEach(item => {
        delete item.order
        delete item.orderIndex
      })
  
      let sortInfoMap = {}
      sortInfo.forEach((item) => {
        if (item.order) {
          sortInfoMap[item.prop] = item
        }
      })
      unref(self.columns).forEach(item => {
        if (item.prop in sortInfoMap) {
          item.order = sortInfoMap[item.prop].order
          item.orderIndex = sortInfoMap[item.prop].orderIndex
        }
      })
    }
  }
  unref(self.columns).forEach( ele => {
    if (ele.order) {
      ele.order_ori = ele.order
    }
  })
  self.loadSort();

  self.query = ref({})

  for(let i in queryInfoList) {
    i = queryInfoList[i]
    if (i.hide === true) {
      continue;
    }
    if (i.prop === 'workspace_name' && workspaceName) {
      i.default = workspaceName
      self.query.value[i.prop] = i.default
      continue;
    }
    
    let v = getStorageValue('query_'+self.name.value+'_'+i.prop)
    try {
      const newV = JSON.parse(v)
      if (newV instanceof Array) {
        v = newV
      }
    }catch(ex) {

    }
    if (v || v === 0) {
      self.query.value[i.prop] = v;
    }
  }

  self.init_remote_list = (columns, param)  => {
    let { query } = param
    columns.forEach( column => {
      let r = column.list_remote
      if (r && r.mode !== 'dynamic') {
        column.list = []
        let r_query = {...(r.query || {})}
        post(r.module, r.method, r_query, {sortInfo:r.sortInfo})
        .then( data => {
          data.forEach( item => {
              column.list.push({ label:item[r.mapInfo.label], value:item[r.mapInfo.value], data: item})
            })
          let cb = r.cb
          if (typeof(cb) == 'string') {
            cb = ((columns.find( item2 => item2.prop == cb) || {}).list_remote || {}).cb
          }
          if(cb) {
            cb({...self, mode: 'remote init', column, columns, data})
          }
        })
      }      
    })
  }

  self.init_remote_list(self.queryColumns.value, {query: unref(self.query)})

  self.selectRows = ref([])

  self.multipleTable = ref(null)

  self.tablePagination = ref(null)

  self.sortColumns = ref([])

  self.tableData = ref([]);
  self.pageTotal = ref(0);

  self.discardCount = ref(false)

  self.loadingSearch = ref(false)

  self.loadingDelete = ref(false)

  self.loadingExport = ref(false)

  self.pageSizes = ref([10,50,100,1000])

  self.editDialog = ref(null)
  self.editForm = ref(null)

  self.form_rules = ref([])

  self.editTitle = ref('')
  self.editVisible = ref(false)
  self.form = ref({})
  self.form_ori = ref({})

  self.onTableSelectionChange = (a, b, c) => {
    self.selectRows.value = a
  }

  self.get_remote_list = params => {
    let {columns, prop, query, form} = params
    try {
      let column = columns.find( item => item.prop == prop);
      if (!column || !column.list_remote) {
        let msg = '未找到属性:'+prop
        ElMessage.error(msg);
        return Promise.reject(new Error(msg));
      }
      const r = column.list_remote
  
      query = {...r.query, ...query}
      return post(r.module, r.method, query, {sortInfo:r.sortInfo})
      .then( data => {
        column.list = []
        data.forEach( item => {
          column.list.push({ label:item[r.mapInfo.label], value:item[r.mapInfo.value], data: item})
        })
        let cb = r.cb
        if (typeof(cb) == 'string') {
          cb = ((columns.find( item2 => item2.prop == cb) || {}).list_remote || {}).cb
        }
        if(cb) {
          cb({...self, ...params, column, columns, data})
        }
        return {...self, ...params, column, data}
      })
    }catch(ex) {
      console.error('get_remote_list fail', ex)
      ElMessage.error('无法获取信息'+ex);
      return Promise.reject(new Error(ex));
    }
  }

  const set_query_storage = (form, prop, value) => {
    form[prop] = value
    setStorageValue('query_'+self.name.value+'_'+prop, value)
  }

  self.set_query_storage = set_query_storage

  const onChange = (param) => {
    const {mode, form, column, columns} = param
    // console.log('onChange', mode, form, column, param)
    if (mode == 'query') {
      self.discardCount.value = false
    }
    if (form[column.prop] instanceof Array) {
      let newForm = []
      let foundBlank = false
      form[column.prop].forEach( item => {
        if (item === '') {
          foundBlank = true
        } else {
          newForm.push(item)
        }
      })
      if (foundBlank && newForm.length > 0) {
        form[column.prop] = newForm
      }
    }
    if (mode == 'query') {
      if (column.prop == 'workspace_name') {
        setStorageValue('workspace_name', form[column.prop])
      } else {
        setStorageValue('query_'+self.name.value+'_'+column.prop, form[column.prop])
      }
    }

    if (mode !== 'dialog' && column.oninit) {
      let cb = column.oninit
      if (typeof(cb) == 'string') {
        cb = (columns.find( item2 => item2.prop == column.oninit) || {}).oninit
      }
      if(cb) {
        cb({...self, ...param})
      }
    } else if (column.onchange) {
      let cb = column.onchange
      if (typeof(cb) == 'string') {
        cb = (columns.find( item2 => item2.prop == column.onchange) || {}).onchange
      }
      if(cb) {
        cb({...self, ...param})
      }
    }
  }

  const onFocus = (param) => {
    const {mode, form, column, columns} = param

    if (column.onfocus) {
      let cb = column.onfocus
      if (typeof(cb) == 'string') {
        cb = (columns.find( item2 => item2.prop == column.onfocus) || {}).onfocus
      }
      if(cb) {
        cb({...self, ...param})
      }
    }
  }

  self.sortMethod = a => {
    if (a) {
      let column = self.columns.value.find((item) => item.prop === a.property)
      if (column.order === 'desc' || column.order === 'desc/gbk') {
        column.order = null
        column.orderIndex = null
      } else if (column.sort_by_gbk) {
        if (column.order === 'asc/gbk' || column.order === 'asc') {
          // column.order = 'desc/gbk'
          column.order = 'desc'
        } else {
          // column.order = 'asc/gbk'
          column.order = 'asc'
        }
      } else {
        if (column.order === 'asc') {
          column.order = 'desc'
        } else {
          column.order = 'asc'
        }
      }
      if (column.order) {
        if (!column.orderIndex) {
          column.orderIndex = 0
          unref(self.columns).forEach((item) => {
            if (item.order && item.orderIndex > column.orderIndex) {
              column.orderIndex = item.orderIndex
            }
          })
          column.orderIndex++
        }
      } else {
        column.column_index = null
      }
      let orderList = []
      unref(self.columns).forEach ( item => {
        if (item.order && item.orderIndex >= 0) {
          orderList.push({prop: item.prop, order: item.order, orderIndex: item.orderIndex})
        }
      })
      setStorageValue(
        'order_' + self.name.value,
        orderList
      )
    }

    self.sortColumns.value = []
    unref(self.columns).forEach((item) => {
      if (item.order) {
        self.sortColumns.value.push(item)
      }
    })
    let sortCondition = []
    unref(self.sortColumns)
    .sort(function compareFunction(param1, param2) {
        return param1.orderIndex - param2.orderIndex
      })
      .forEach((item) => {
        item.orderIndex = sortCondition.length + 1
        let sortItem = new Object()
        sortItem[item.prop] = item.order
        sortCondition.push(sortItem)
      })

  }

  self.onRowClick = (a) => {
    if (unref(self.selectRows).length > 1) {
      let found = false
      unref(self.selectRows).forEach((item) => {
        if (item.id === a.id) {
          found = true
        }
      })
      if (found) {
        return
      }
      ElMessageBox.confirm('是否要取消其他选择状态？', '警告', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        closeOnClickModal: false,
        type: 'warning',
      })
        .then(() => {
          if (unref(self.multipleTable).clearSelection) {
            unref(self.multipleTable).clearSelection()
          }
          if (unref(self.multipleTable).toggleRowSelection) {
            unref(self.multipleTable).toggleRowSelection(a)
          }
        })
        .catch(err => {
          if (unref(self.multipleTable).toggleRowSelection) {
            unref(self.multipleTable).toggleRowSelection(a)
          }
        })
    } else {
      if (unref(self.multipleTable).clearSelection) {
        unref(self.multipleTable).clearSelection()
      }
      if (unref(self.multipleTable).toggleRowSelection) {
        unref(self.multipleTable).toggleRowSelection(a)
      }
    }
  }

  self.processData = (data) => {
    try {
      // if (self.custom.processDataPre) {
      //   self.custom.processDataPre(data)
      // }
      const donePropSet = {}
      if (data && data.length && self.columns.value && self.columns.value.length) {
        let index = 1
        const columnnMap = {}
        data.forEach( item => {
          // item['#'] = index++
  
          for(const p in item) {
            let column = donePropSet[p]
            if (!column) {
              column = self.columns.value.find( column1 => column1.prop == p)
              if (!column) {
                column = {
                  prop: p,
                  label: p,
                }
                donePropSet[p] = column
                self.columns.value.push(column)
              }
            }
            if (column.oninit) {
              let cb = column.oninit
              if (typeof(cb) == 'string') {
                cb = (self.columns.value.find( item2 => item2.prop == cb) || {}).oninit
              }
              if (cb) {
                cb({...self, mode: 'init_data', form: item, column, columns: self.columns.value})
              }
            }
          }
        })

        // if (self.custom.processData) {
        //   self.custom.processData(data, self)
        // }
      }
    } catch(ex) {
      console.error('processData ex', ex)
    }
  }
  
  self.forceRefreshAfterUpdate = ref(false)

  self.cellClick = (row, column, cell, event) => {
    self.last_click_cell = {row, column, cell, property: column.property}
  }

  self.getData = (param) => {
    let { pageNo, pageSize, queryExtraParam, withoutSetData, withoutProcessParam } = param || {}
    self.forceRefreshAfterUpdate.value = false;
    let remoteCount = self.remoteConfig.value.count
    if (!remoteCount) {
      let msg = '未定义count'
      ElMessage.error(msg)
      return Promise.reject(msg);
    }
    let remoteList = self.remoteConfig.value.list
    if (!remoteList) {
      let msg = '未定义list'
      ElMessage.error(msg)
      return Promise.reject(msg);
    }
    if (self.loadingSearch.value) {
      ElMessage.error('正在查询，请稍后再试')
      return Promise.resolve();
    }
    self.loadingSearch.value = true;
    let query = fixBlankFileds(self.query.value)
    if (!query) {
      query = {}
    }
    if (withoutProcessParam) {
      if (query.query_options) {
        delete query.query_options.like
      }
    } else {
      let hasLike = false
      if (!query.query_options) {
        query.query_options = {}
      }
      let like = {}
      Object.keys(query).forEach( ele => {
        if (ele.indexOf('_like') >= 0) {
          if (query[ele]) {
            like[ele.replace('_like', '')] = '%' + query[ele] + '%'
            hasLike = true
            delete query[ele]
          }
        }
      })
      if (hasLike) {
        query.query_options['like'] = like
      } else {
        delete query.query_options.like
      }
      if (self.columns.value.find(ele => ele.prop == 'workspace_name')) {
        if (self.query.value.workspace_name) {
          setStorageValue('workspace_name', self.query.value.workspace_name)
        } else {
          setStorageValue('workspace_name', null)
        }
      }
    }

    if (self.sortColumns.value.length) {
      if (!('query_options' in query)) {
        query.query_options = {}
      }
      query.query_options.order_by = []
      self.sortColumns.value.forEach( item => {
        let newItem = {}
        newItem[item.prop] = item.order
        query.query_options.order_by.push(newItem)
      })
    }
    if (pageNo) {
      query.pageNo = pageNo
    }
    if (pageSize) {
      query.pageSize = pageSize
    }
    if (queryExtraParam) {
      query = {...query, ...queryExtraParam}
    }
    if (!query.pageSize) {
      let pageSize = getStorageValue('pageSize')
      if (!pageSize) {
        pageSize = 10
      } else {
        pageSize = parseInt(pageSize)
      }
      query.pageSize = pageSize
      self.query.value.pageSize = pageSize
    }

    
    let now = new Date()

    let count = null
    return post(remoteList.module, remoteList.method, query, {withConfig: true})
    .then(response => {
      let { data, config } = response
      if (data.code && data.msg) {
        throw new Error(data.msg)
      }
      if (data.body) {
        data = data.body
      } else {
        throw new Error('返回结果错误:'+JSON.stringify(data))
      }
      if (response.headers['count']) {
        count = parseInt(response.headers['count'])
        self.pageTotal.value = count
      }
      if ((new Date()).getTime() - now.getTime() > 30*1000) {
        console.log('after getData,', (new Date()).getTime() - now.getTime(), new Date())
      }
      self.processData(data)
      if (withoutSetData) {
        return data;
      }
      self.tableData.value = data
      return data
    })
    .then( data => {
      count = null
      self.discardCount.value = false
      if (count === null) {
        if (!((param||{}).forceCount) && self.discardCount.value) {
          self.loadingSearch.value = false;
        } else {
          return post(remoteCount.module, remoteCount.method, query)
          .then ( data2 => {
            self.loadingSearch.value = false;
            self.discardCount.value = true
            if ((new Date()).getTime() - now.getTime() > 30*1000) {
              console.log('after countData,', (new Date()).getTime() - now.getTime(), new Date())
            }
            now = new Date();
            self.pageTotal.value = data2
            return data
          })
        }
      } else {
        self.loadingSearch.value = false;
        self.discardCount.value = true
      }
      return data
    })
    .catch(err => {
      self.loadingSearch.value = false;
      ElMessage.error(`无法获取数据：${err}`)
      return Promise.reject(`无法获取数据:${err}`);
    })
  };

  self.resetSort = (param) => {
    ElMessageBox.confirm("确定要清空所有查询条件并重置排序字段吗？", "提示", {
      type: "warning",
    }).then(() => {
        let items = []
        for(let i = 0; i < localStorage.length; i++) {
          let key = localStorage.key(i)
          if (key.indexOf('query_'+unref(self.name) + '_') == 0) {
            items.push(key)
          }
        }
        items.push('order_'+unref(self.name))
        items.forEach( ele => {
          removeStorageValue(ele)
        })

        Object.keys(unref(self.query)).forEach(ele => {
          delete unref(self.query)[ele]
        })

        removeStorageValue('workspace_name')

        self.loadSort()
    })
  }

  self.lastCurrentRow = null
  self.handleCurrentChange = (param) => {
    if(param){
      self.lastCurrentRow = param
    }
  }

  self.handleSearch = (param) => {
    let selectRows = [...unref(self.selectRows)]
    let tableData = [...unref(self.tableData)]
    return self.getData(param)
    .then( data => {
      let firstRow
      let lastCurrentRow = self.lastCurrentRow
      unref(self.tableData).forEach( (ele, index) => {
        if(lastCurrentRow && lastCurrentRow.id == ele.id){
          firstRow = ele
        }
        let item = selectRows.find(e => e.id == ele.id)
        if (item) {
          if (unref(self.multipleTable).toggleRowSelection) {
            
            unref(self.multipleTable).toggleRowSelection(ele, true)
          }
        }
        item = tableData.find(e => e.id == ele.id)
        if (item && item.name_diff) {
          ele.name_diff = item.name_diff
        }
        if (firstRow) {
            unref(self.multipleTable).setCurrentRow(firstRow)
        }
      })
      return data
    })
  };

  self.handlePageChange = (val) => {
    self.query.value.pageNo = val;
    return self.handleSearch();
  };

  self.handleSizeChange = (val) => {
    self.query.value.pageSize = val;
    setStorageValue('pageSize', val)
  }

  self.handleExport = (a, b, c, d, e, form) => {

    let remote = self.remoteConfig.value.export_excel
    if (!remote) {
      ElMessage.error('未定义export_excel方法')
      return;
    }
    let discards = {}
    if (remote.discards) {
      remote.discards.forEach ( item => {
        discards[item] = 1
      })
    }

    let fields = []
    let export_excel_fields = []
    self.columns.value.forEach( item => {
      if (item.prop in discards) {
        return
      }
      if (item.hide) {
        return;
      }
      if (item.discard_export) {
        return;
      }
      fields.push(item.prop);
      export_excel_fields.push({prop:item.prop, title:item.label, width:(item.width || 200)/10})
    })

    self.loadingExport.value = true;
    let query = {
      ...fixBlankFileds(form || self.query.value),
      pageNo:undefined, pageSize:undefined,
      export_excel_fields,
    }

    if (!query) {
      query = {}
    }

    if (self.sortColumns.value.length) {
      if (!('query_options' in query)) {
        query.query_options = {}
      }
      query.query_options.order_by = []
      self.sortColumns.value.forEach( item => {
        let newItem = {}
        newItem[item.prop] = item.order
        query.query_options.order_by.push(newItem)
      })
    }

    if (self.custom.extra_export_query) {
      query = {...self.custom.extra_export_query, ...query}
    }
    if (self.custom.extra_export_columns && query.export_excel_fields) {
      for(const extraProp in self.custom.extra_export_columns) {
        const newArr = []
        for(const columnIndex in query.export_excel_fields) {
          const column = query.export_excel_fields[columnIndex]
          if (column.prop == extraProp) {
            for(let i = 0; i <= columnIndex; i++) {
              newArr.push(query.export_excel_fields[i])
            }
            for(let i = 0; i < self.custom.extra_export_columns[extraProp].length; i++) {
              newArr.push(self.custom.extra_export_columns[extraProp][i])
            }
            for(let i = columnIndex + 1; i < query.export_excel_fields.length; i++) {
              newArr.push(query.export_excel_fields[i])
            }
            break
          }
        }
        query.export_excel_fields = newArr
      }
    }

    post(remote.module, remote.method, query, {responseType: 'arraybuffer'})
    .then( data => {
      self.loadingExport.value = false;
      let link = document.createElement('a')
      let blob = new Blob([data], {
        type: 'application/vnd.ms-excel'
      })
      link.href = window.URL.createObjectURL(blob)
      link.download = self.module.value + '_' + dayjs().format('YYYYMMDDHHmmss') + '.xls'
      document.body.appendChild(link)
      link.click()
    })
    .catch(err => {
      ElMessage.error(`失败:${err}`, err);
      self.loadingExport.value = false;
    })
  }

  self.handleDelete = (index) => {
    if (self.selectRows.value.length == 0) {
      ElMessage.error('请先选择记录');
      return;
    }
      // 二次确认删除
      ElMessageBox.confirm("确定要删除吗？", "提示", {
          type: "warning",
      })
          .then(() => {
            let remote = self.remoteConfig.value.delete
            if (!remote.keys || remote.keys.length == 0) {
              ElMessage.error(`未配置keys:${remote}`);
              return;
            }
      
            self.loadingDelete.value = true;
            let form = {}
            remote.keys.forEach( key => {
              form[key] = []
              self.selectRows.value.forEach( row => {
                form[key].push(row[key])
              })
            })
            
            self.discardCount.value = false
            post(remote.module, remote.method, form)
            .then( data => {
              if (data) {
                ElMessage.success(`成功`);
                let selectRows = [...unref(self.selectRows)]
                let selectIndex = -1
                unref(self.tableData).forEach( (ele, index) => {
                  let item = selectRows.find(e => selectRows[0].id == ele.id)
                  if (item) {
                    selectIndex = index
                  }
                })
                self.loadingDelete.value = false;
                return self.handleSearch({forceCount:true})
                .then( data => {
                  if (selectIndex !== -1 && selectIndex < unref(self.tableData).length) {
                    if (unref(self.multipleTable).toggleRowSelection) {
                      unref(self.multipleTable).toggleRowSelection(unref(self.tableData)[selectIndex], true)
                    }
                  }
                })
              } else {
                ElMessage.error(`失败:${data}`);
                self.loadingDelete.value = false;
              }
            })
            .catch(err => {
              ElMessage.error(`失败:${err}`, err);
              self.loadingDelete.value = false;
            })
          })
          .catch(err => {
            ElMessage.error(`失败:${err}`, err);
            self.loadingDelete.value = false;
          });
  };

  self.getFormAndcheckRequired = ({form, columns}) => {
    let newForm = fixBlankFileds(form, null, columns)
    for(let item in columns) {
      item = columns[item]
      if (item.prop == 'updated_at'
        || item.prop == 'updatedby'
        || item.prop == '#'
      ) {
        continue;
      }
      if (item.required) {
        if (!newForm || !(item.prop in newForm) || !newForm[item.prop]) {
          ElMessage.error(`请输入:${item.label}`);
          return null;
        }
      }
    }
    return newForm
  }

  self.baseMounted = (v) => {
    for(let p in v) {
      self[p].value = v[p].value;
    }
  }

  self.cellDblclick = (row, propItem) => {
    if (row && propItem && row[propItem.property]) {
      let v = row[propItem.property] + ''
      if (v.length >= 20) {
        ElMessageBox({
          message: h('textarea', {rows: '20'}, row[propItem.property]),
          customClass:'cellDblclickClass',
        })
      }
    }
  }

  const getOnlySelectRowData = (selectRows) => {
    if (!selectRows || selectRows.length == 0) {
      ElMessage.error('请先选择记录');
      return null;
    }
    if (selectRows.length > 1) {
      ElMessage.error('只能选择一条记录进行编辑');
      return null;
    }
    return selectRows[0]
  }

  self.getOnlySelectRowData = getOnlySelectRowData

  self.handleSearchButton = ref({
    showMenu: false,

  })

  self.showQueryColumnsButton = ref({
    changed: 0,
    title: '',
    icon: '',
    showAll: false,
    onclick: param => {
      let button = unref(self.showQueryColumnsButton)
      button.showAll = button.showAll ? 0 : 1;
      button.icon = button.showAll ? ArrowLeft : ArrowRight
      setStorageValue('showAllQueryColumns', button.showAll)
      button.title = button.showAll? '隐藏空查询条件' : '显示所有查询条件'
      if (button.showAll) {
        button.changed = 0;
      }
    }
  })

  {
    let showAllQueryColumns = getStorageValue('showAllQueryColumns')
    let button = unref(self.showQueryColumnsButton)
    if (showAllQueryColumns === null || showAllQueryColumns === undefined) {
      button.showAll = 0;
    } else {
      button.showAll = showAllQueryColumns ? 0 : 1
    }
    button.onclick()
  }

  self.amis = {
    throw: (msg) => {
      console.error('throw', msg)
      self.amis.toast.error(msg)
      throw new Error(msg)
    },
    enableDialogDrag: function() {
      let qutoContainer = document.getElementsByClassName('cxd-Modal-content');
      if (!qutoContainer || !qutoContainer.length) {
        return
      }
      qutoContainer = qutoContainer[0]
      window.__dialogContainerOri = {}
      qutoContainer.onmousedown = (eventDown) => {
        let style = window.getComputedStyle(qutoContainer);
        window.__dialogContainerOri.marginLeftOri = parseInt(style.marginLeft.replace('px', ''))
        window.__dialogContainerOri.marginTopOri = parseInt(style.marginTop.replace('px', ''))
        window.__dialogContainerOri.downX = eventDown.clientX;
        window.__dialogContainerOri.downY = eventDown.clientY;
        window.__dialogContainerOri.down = 1
        if (window.__dialogContainerOri.downY > window.__dialogContainerOri.marginTopOri + 60) {
          return;
        }
        window.__dialogContainerOri.onmousemove = document.onmousemove
        window.__dialogContainerOri.onmouseup = document.onmouseup
        document.onmousemove = (event) => {
          if (!event.buttons && window.__dialogContainerOri.down) {
            console.log('no buttons down')
            document.onmousemove = window.__dialogContainerOri.onmousemove
            document.onmouseup = window.__dialogContainerOri.onmouseup
            delete window.__dialogContainerOri.onmousemove
            delete window.__dialogContainerOri.onmouseup
            window.__dialogContainerOri.down = 0
            return;
          }
          event.stopPropagation();
          const moveX = event.clientX - window.__dialogContainerOri.downX;
          const moveY = event.clientY - window.__dialogContainerOri.downY;
          if (moveX && window.__dialogContainerOri.downX + moveX < document.body.clientWidth) {
            qutoContainer.style.marginLeft = (window.__dialogContainerOri.marginLeftOri + moveX) + 'px'
          }
          if (moveY && window.__dialogContainerOri.downY + moveY < document.body.clientWidth ) {
            let newY = (window.__dialogContainerOri.marginTopOri + moveY) + 'px'
            qutoContainer.style.marginTop = (window.__dialogContainerOri.marginTopOri + moveY) + 'px'
          }
        };
        document.onmouseup = () => {
          document.onmousemove = window.__dialogContainerOri.onmousemove
          document.onmouseup = window.__dialogContainerOri.onmouseup
          delete window.__dialogContainerOri.onmousemove
          delete window.__dialogContainerOri.onmouseup
          window.__dialogContainerOri.down = 0
        }
      }
    },
    
    showInfo: (msg) => {
      self.amis.toast.info(msg)
    },
    getComponentByIdAndType: (info, id, type) => {
      if (!info || !info[id]) {
        return;
      }
      if (info[id].component.props.type == type) {
        return info[id]
      }
      return self.amis.getComponentByIdAndType(info, info[id].parent_id, type)
    },
    getComponentListByType: (info, type) => {
      if (!info) {
        return;
      }
      let ret = []
      for(let p in info) {
        if (info[p].type == type) {
          let item = {}
          item[p] = info[p]
          ret.push(item)
        }
      }
      return ret;
    },
    getObjectFirstPropValue: o => {
      let keys = Object.keys(o)
      if (keys && keys.length) {
        return o[keys[0]]
      }
    },
    getComponentsInfo:(id) => {
      let e = self.amis.amisInstance.getComponents()
      let count = 0
      let path = {}
      let components = {}
      let f = (e, parent_id) => {
        if (count++ > 100000) {
          return;
        }
        if (!e) {
          return;
        }
        let cs;
        if (e.context && e.context.getComponents) {
          cs = e.context.getComponents()
        } else {
          cs = e;
        }
        if (cs && cs.length) {
          for(let i in cs) {
            if (!path[cs[i].props.$path]) {
              path[cs[i].props.$path] = cs[i]
              f(cs[i], cs[i].props.store.id)
            }

            if (cs[i].props.formItem && cs[i].props.formItem.id) {
              components[cs[i].props.formItem.id] = {parent_id, type: cs[i].props.type, parent_component:e, component:cs[i]}
            } else if(cs[i].props.store && cs[i].props.store.id){
              components[cs[i].props.store.id] = {parent_id, type: cs[i].props.type, parent_component:e, component:cs[i]}
            }
          }
        }
        return
      }
      f(e)
      for(let p in components) {
        components[p].childs = {}
        for(let k in components) {
          if (components[k].parent_id == p) {
            components[p].childs[k] = components[k]
          }
          if (k == components[p].parent_id) {
            components[p].parent = {}
            components[p].parent[k] = components[k]
          }
        }
      }
      console.log('getComponentsInfo', components)
      if (id) {
        return components[id]
      }
      return components
    },
    dupColumns:(more_fields) => {
      if (more_fields && more_fields.indexOf('batchUpdateValue') >= 0) {
        return [
          {
            name: 'update_value_name',
            label: '字段',
            required: true,
            type: 'select',
            options: [...unref(self.columns).filter(ele => ele.prop && ele.prop != 'id').map(ele => {
              let item = {...ele}
              if (item.label && item.label != item.prop) {
                return {label: item.label + ' - ' + item.prop, value: item.prop};
              } else {
                return {label: item.prop, value: item.prop};
              }
            })]
          },
          {
            name: 'update_value_value',
            required: true,
            type: 'input-text',
            label: '被替换的原值',
          },
          {
            name: 'update_value_dest_value',
            type: 'input-text',
            label: '要替换为',
          },
        ]
      }
      return [  
        ...unref(self.columns).filter(ele => ele.prop).map(ele => {
          let item = {...ele}
          if (!item.label) {
            item.label = item.name
          } else if (item.label !== item.name) {
            if (item.name !== 'name' && item.name !== 'workspace_name' && item.name != 'remark') {
              item.label = item.label+'('+item.name+')'
            }
          }
          if (more_fields) {
            more_fields.split(',').forEach(c => {
              c = c.trim()
              if (c && ele[c]) {
                item = {...item, ...ele[c]}
              }
            })
          }
          if (!item.type) {
            item.type = 'text'
          }
          if (more_fields && more_fields.indexOf('edit') >= 0 && item.type == 'text') {
            item.type = 'input-text'
          }
          return item;
        }),
      ]
    },
    onEventCreateFile: {
      click: {
        actions: [
          {
            actionType: "custom",
            script: (a,b,c,d,e,f) => {
              self.amis.onAction(a,b,c,d,e,f, {type: 'create_file', module: unref(self.module)})
            }
          },
        ]
      },
    },
    onEventEditSubmit: {
      click: {
        actions: [
          {
            actionType: "custom",
            script: (a,b,c,d,e,f) => {
              self.amis.onAction(a,b,c,d,e,f, { type:'edit', module:unref(self.module),})
            },
          },
        ],
      },
    },
    onEventDelete: {
      click: {
        actions: [
          {
            actionType: "custom",
            script: (a,b,c,d,e,f) => {
              self.amis.onAction(a,b,c,d,e,f, {type: 'delete', module: unref(self.module)})
            }
          },
        ]
      },
    },
    onEventBatchDelete: {
      click: {
        actions: [
          {
            actionType: "custom",
            script: (a,b,c,d,e,f) => {
              self.amis.onAction(a,b,c,d,e,f, {type: 'batchDelete', module: unref(self.module)})
            }
          },
        ]
      },
    },
    page_schema: {
      type: "page",
      id: 'u:page',
      asideResizor: false,
      data: {
        title : unref(self.title),
        button_add_visible: self.button_add_visible,
        button_item_edit_visible: self.button_item_edit_visible,
      },
      style: {
        boxShadow: " 0px 0px 0px 0px transparent",
      },
    },
    init: (param) => {
      let {
        columns,
        insert_edit_bulk_actions,
        insert_edit_actions,
        append_header_actions,
        insert_header_actions,
      } = param
      self.columns.value = self.amis.fixColumns(columns)

      self.amis = {
        ...self.amis,
        commonSchema: {
          crud: {
            syncLocation: false,
            checkOnItemClick: true,
            
            selectable: true,
            multiple: true,
            columnsTogglable: true,
            
            api: {
              method: "post",
              url: "dummy",
              custom:{
                module: unref(self.module),
                method: 'list',
                method_total: 'count',
                requestAdaptor: 'query',
              },
              dataType: "json",
              
              requestAdaptor: api => {
                return self.amis.requestAdaptor(api)
              },
              
            },
            showFooter: false,
            filterTogglable: true,
            // footerToolbar: [
            //   "statistics",
            //   "switch-per-page",
            //   "pagination",
            // ],
            // alwaysShowPagination: true,
            perPageAvailable: [
              10,
              20,
              50,
              100,
              200,
            ],
            headerToolbar: [
              {
                type: 'pagination',
                "layout": "pager,perPage",
                "maxButtons": 5,
                "showPageInput": false,
                onPageChange: (a,b,c,d) => {
                  console.log('onPageChange', a, b, c, c)
                },
                align: 'normal',
              },
              {
                type: 'tpl',
                tpl: '共 ${total}项',
                align: 'normal',
              },
              "filter-toggler",
              "bulkActions",
              ...(append_header_actions || []),
              ...(insert_header_actions||[]),
              {
                type: "button",
                align: "right",
                // limits: "add",
                actionType: "dialog",
                label: "添加",
                visibleOn: "${button_add_visible !== false}",
                icon: "fa fa-plus pull-left",
                size: "sm",
                primary: true,
                dialog: {
                  title: "添加",
                  size: "md",
                  body: {
                    type: "form",
                    onInit:(a,b,c,d,e,f) => {
                      self.amis.enableDialogDrag();
                    },
                    api:{
                      method: "post",
                      url: "api2/"+unref(self.module)+"/add",
                      dataType: "json",
                    },
                    body: self.amis.dupColumns('edit,add'),
                  },
                },
              },
            ],
            columns: [        
              ...self.amis.dupColumns(),
              {
                "type": "button-group",
                label: "操作",
                name: "operation",
                "fixed": "right",
                buttons: [
                  {
                    "type": "button",
                    level: "danger",
                    "label": "删除",
                    loadingOn:'${button_delete_loading}',
                    onEvent: self.amis.onEventDelete,
                    "confirmText": "确定要删除 (${id}) : ${name}？"
                  },
                  {
                    "type": "button",
                    "label": "编辑",
                    visibleOn: "${button_item_edit_visible !== false}",
                    actionType: "dialog",
                    
                    dialog: {
                      title: "编辑 - ${name}",
                      name: 'd:edit',
                      size: "md",
                      "actions": [
                        ...(insert_edit_actions || []),
                        {
                          type: 'submit',
                          label: '取消',
                        },
                        {
                          "type": "button",
                          "label": "确认",
                          level: 'primary',
                          loadingOn: "${button_batch_edit_loading}",
                          onEvent: self.amis.onEventEditSubmit,
                        },
                      ],
                      body: {
                        type: "form",
                        onInit:(a,b,c,d,e,f) => {
                          self.amis.enableDialogDrag();
                        },
                        body: self.amis.dupColumns('edit'),
                        id: "u:edit",
                      },
                      id: 'u:dialog',
                    },
                  },
                ],
              },
            ],
          },
          bulkActions: {
            batchUpdateValue: {
              type: "button",
              label: "批量替换值",
              onEvent: {
                click: {
                  actions: [
                    {
                      actionType: "custom",
                      script: (a,b,c,d,e,f) => {
                        console.log('custom', a,b,c,d,e,f)
                        let txt = getSelection() || '';
                        b({
                          actionType: "dialog",
                          dialog: {
                            title: "批量替换值",
                            size: "md",
                            "actions": [
                              {
                                type: 'button',
                                label: '取消',
                                onEvent: {
                                  click: {
                                    actions: [
                                      {
                                        actionType: "closeDialog",
                                      },
                                    ]
                                  },
                                }
                              },
                              {
                                "type": "button",
                                "label": "确认",
                                level: 'primary',
                                loadingOn: "${button_batch_update_value_loading}",
                                onEvent: {
                                  click: {
                                    actions: [
                                      {
                                        actionType: "custom",
                                        script: (a,b,c,d,e,f) => {
                                          self.amis.onAction(a,b,c,d,e,f, {type: 'updateValue', module: unref(self.module)})
                                        }
                                      },
                                    ]
                                  },
                                }
                              },
                            ],
                            body: {
                              type: "form",
                              data: {
                                update_value_value: txt,
                                update_value_dest_value: txt,
                              },
                              onInit:(a,b,c,d,e,f) => {
                                self.amis.enableDialogDrag();
                              },
                              body: self.amis.dupColumns('batchUpdateValue'),
                            },
                          },
                        })
                      },
                    }

                  ]
                }
              }
            },
            delete: {
              type: "button",
              level: "danger",
              label: "批量删除",
              confirmText: "确定要批量删除？",
              loadingOn: "${button_batch_delete_loading}",
              onEvent: self.amis.onEventBatchDelete,
            },
            edit: {
              type: "button",
              label: "批量编辑",
              actionType: "dialog",
              dialog: {
                title: "批量编辑",
                size: "md",
                "actions": [
                  ...(insert_edit_bulk_actions || []),
                  {
                    type: 'submit',
                    label: '取消',
                  },
                  {
                    "type": "button",
                    "label": "确认",
                    level: 'primary',
                    loadingOn: "${button_batch_edit_loading}",
                    onEvent: self.amis.onEventEditSubmit,
                  },
                ],
                body: {
                  type: "form",
                  onInit:(a,b,c,d,e,f) => {
                    self.amis.enableDialogDrag();
                  },
                  body: self.amis.dupColumns('edit,batchEdit'),
                },
              },
            },
          },
          filter: {
            page_title: {
              type: "input-text",
              name: "$title",
              className: 'c-page-title',
              label: false,
              value: '${title}',
              "borderMode": "none",
              static: true,
            },
            workspace_name:{
              type: "select",
              name: "workspace_name",
              clearable: true,
              size:'sm',
              placeholder: "请选择工作区",
              source: {
                method: "post",
                url: "api2/sdp_workspace/list",
                requestAdaptor(api) {
                  let param = {}
                  let data = api.body
                  let keys = Object.keys(data)
                  for(let p in keys) {
                    p = keys[p]
                    
                    let v = data[p]
                    if (p == 'page') {
                    } else if (p == 'perPage') {
                    } else if (v === '') {
                      param[p] = v
                    }
                  }
                  api.data = param
                  return api
                },
                responseData: {
                  options: "${body|pick:label~name,value~name}"
                },
              },
            },
            search:{
              type: "control",
              className: "m-l",
              body: [              
                {
                  type: "submit",
                  label: "搜索",
                },
              ],
            },
          }
        },
        pageValue: ref({
        }),
        pageComponentId: 'u:page',
        amisInstance:'',
      }
    },
    
    fixColumns: (columns) => {
      return [...unref(self.columns).filter(ele => ele.prop).map(ele => {
        ele.name = ele.prop
        let n = columns.find(c => c.name == ele.prop)
        if (n) {
          ele = {...ele, ...n}
        }
        if (ele.prop == 'workspace_name') {
          if (ele.sortable === undefined || ele.sortable === null) {
            ele.sortable = true;
          }
          if (ele.toggable === undefined || ele.toggable === null) {
            ele.toggable = false
          }
        } else if (ele.prop == 'id') {
          if (ele.sortable === undefined || ele.sortable === null) {
            ele.sortable = true;
          }
          if (ele.toggled === undefined || ele.toggled === null) {
            ele.toggled = false;
          }
          if (!ele.edit) {
            ele.edit = {}
          }
          if (ele.edit.type === undefined || ele.edit.type === null) {
            ele.edit.type = 'hidden'
          }
        } else if(ele.prop == 'name') {
          if (ele.sortable === undefined || ele.sortable === null) {
            ele.sortable = true;
          }
          if (!ele.edit) {
            ele.edit = {}
          }
          if (ele.edit.required === undefined || ele.edit.required === null) {
            ele.edit.required = true
          }
          if (!ele.batchEdit) {
            ele.batchEdit = {}
          }
          if (ele.batchEdit.disabledOn === undefined || ele.batchEdit.disabledOn === null) {
            ele.batchEdit.disabledOn = "${selectedItems.length > 1}"
          }
          if (ele.toggable === undefined || ele.toggable === null) {
            ele.toggable = false
          }
        } else {
          if (!ele.edit) {
            ele.edit = {}
          }
          if (ele.edit.clearable === undefined || ele.edit.clearable === null) {
            ele.edit.clearable = true
          }
        }
        return ele
      })]
    },
    requestAdaptor: (api) => {
      if (api.custom.requestAdaptor == 'query') {
        let param = {}
        let data = api.body
        let keys = Object.keys(data)
        for(let p in keys) {
          p = keys[p]
          
          let v = data[p]
          if (v === '') {

          } else if (p.indexOf('_like') > 0) {
            if( v !== undefined && v !== null && v !== '') {
              
              let name = p.split('_like')[0]
              if (!param.query_options) {
                param.query_options = {}
              }
              if (!param.query_options.like) {
                param.query_options.like = {}
              }
              param.query_options.like[name] = '%'+api.data[p]+'%'
            }
          } else if (p == 'orderBy' || p == 'orderDir') {
            if (data.orderBy) {
              if (!param.query_options) {
                param.query_options = {}
              }
              let order_by = {}
              order_by[data.orderBy] = data.orderDir == 'asc' ? 'asc' : 'desc'
              param.query_options.order_by = [order_by]
            }
          } else if (p == 'page') {
            param['page_no'] = v
          } else if (p == 'perPage') {
            param['page_size'] = v
          } else if (p.indexOf('$') == 0) {
          } else {
            param[p] = v
          }
        }
        api.data = param
      }
      return api;
    },
    setPageValue: (data) => {
      self.amis.pageValue.value = {
        ...self.amis.pageValue.value,
        ...data
      }
    },
    onAction:(a,b,c,d,e,f, options) => {
      let ret = {}
      try {
        console.log('onEvent', a, b, c, d,e,f, self.amis.getComponentsInfo())
        if (a && a.props && a.props.loadingOn && a.props.loadingOn.indexOf('${') == 0 && a.props.loadingOn.indexOf('}') == a.props.loadingOn.length - 1) {
          let name = a.props.loadingOn.substring(2, a.props.loadingOn.length - 1)
          ret.loading_true = {}
          ret.loading_true[name] = true
          ret.loading_false = {}
          ret.loading_false[name] = false
          ret.loading_name = name
        }
        let p = c.context.scoped
        let forms = []
        let dialogs = []
        while(p) {
          let cs = p.getComponents()
          for(let i in cs) {
            if (cs[i].props && cs[i].props.type == 'dialog') {
              dialogs.push(cs[i])
              if (!ret.loadingComponent) {
                ret.loadingComponent = cs[i]
              }
            }
            if (cs[i].props && cs[i].props.type == 'page') {
              if (!ret.pageComponent) {
                ret.pageComponent = cs[i]
              }
            }
            if (cs[i].props && cs[i].props.type == 'crud') {
              if (!ret.crudComponent) {
                ret.crudComponent = cs[i]
              }
            }
            if (cs[i].props && cs[i].props.type == 'form' && cs[i].props.$path.indexOf('/filter/form') > 0) {
              if (!ret.filterComponent) {
                ret.filterComponent = cs[i]
                ret.filter = cs[i].props.data
              }
            }
            if (cs[i].props && cs[i].props.type == 'form') {
              forms.push(cs[i])
              if (!ret.formComponent) {
                ret.formComponent = cs[i]
              }
            }
          }
          p = p.parent
        }
        if (!ret.loadingComponent && ret.pageComponent) {
          ret.loadingComponent = ret.pageComponent
        }
        if (ret.formComponent.props.$path.indexOf('/filter/form') > 0) {
          ret.loadingComponent = ret.pageComponent
        }
        if (!ret.loadingComponent) {
          throw new Error('cannot get loadingComponent')
        }
  
        ret.selectedItems = []
        if (c.data.id) {
          ret.selectedItems = [c.data]
        }
        if (ret.loadingComponent.props && ret.loadingComponent.props.type == 'dialog') {
          if (ret.loadingComponent.props.title
                && ret.loadingComponent.props.title.indexOf('批量') >= 0
                && c.data
                && c.data.__super
                && c.data.__super.selectedItems
                && c.data.__super.selectedItems.length) {
            ret.selectedItems = c.data.__super.selectedItems
          } else {
          }
        } else if (c.data && c.data.selectedItems && c.data.selectedItems.length) {
          ret.selectedItems = c.data.selectedItems
        } else {
          console.log('no selectedItems', c.data, c, a)
        }

        let workspace_name

        if (!ret.selectedItems.length) {
          if (ret.filterComponent && ret.filterComponent.props.data.workspace_name) {
            ret.workspace_name = ret.filterComponent.props.data.workspace_name
          }
        } else {
          let isdiff
          ret.selectedItems.map( ele => {
            if (ele.id) {
              if (workspace_name && workspace_name != ele.workspace_name) {
                isdiff = true
              }
              workspace_name = ele.workspace_name
            }
          })
          if (!isdiff) {
            ret.workspace_name = workspace_name
          }
        }

        let fired = false

        if (options && options.type == 'loading') {
          fired = true
          if (ret.loading_name) {
            if (ret.loadingComponent.getData()[ret.loading_name]) {
              throw new Error('请稍后操作')
            }
            ret.loadingComponent.setData(ret.loading_true)
          }
        }
        if (options && options.type == 'create_file') {
          if (!ret.workspace_name) {
            throw new Error('无法确定生成工作区的名称，请设置工作区条件，或选择一条数据后再操作')
          }
          fired = true
          if (ret.loading_name) {
            if (ret.loadingComponent.getData()[ret.loading_name]) {
              throw new Error('请稍后操作')
            }
            ret.loadingComponent.setData(ret.loading_true)
          }
          ret.selectedItems = [{
            name: JSON.stringify({workspace_name:ret.workspace_name})
          }]
          let count = ret.selectedItems.length
          let id_list = ret.selectedItems.map( ele => {
            post('sdp_project', options.method || 'execute', ele, options.config)
            .then(data => {
              if (count == 1) {
                self.amis.toast.success('成功')

                throw new Error('finish')
              }
              count--;
            })
            .catch(data => {
              count--;
              if (count == 0) {
                ret.crudComponent.handleQuery();
                ret.loadingComponent.setData(ret.loading_false)
                if (data+'' != 'Error: finish') {
                  self.amis.throw(data)
                }
              }
            })
            return ele.id
          })
        }

        if (options && options.type == 'updateValue') {
          if (!c.data.update_value_name) {
            throw new Error('请选择要替换的字段')
          }
          let value = (c.data.update_value_value || '').trim()
          if (!value) {
            throw new Error('请输入要替换的内容')
          }
          let dest_value = (c.data.update_value_dest_value || '').trim()
          if (value == dest_value) {
            throw new Error('原内容和要替换为的内容不能相同')
          }
          fired = true
          if (ret.loading_name) {
            if (ret.loadingComponent.getData()[ret.loading_name]) {
              throw new Error('请稍后操作')
            }
            ret.loadingComponent.setData(ret.loading_true)
          }
          let selectedItems = ret.crudComponent.props.store.selectedItemsAsArray
          if (!selectedItems || !selectedItems.length) {
            throw new Error('请先选择需要替换内容的条目')
          }
          let foundCount = 0
          selectedItems.map( ele => {
            if (ele[c.data.update_value_name]) {
              if (ele[c.data.update_value_name].indexOf(value) >= 0) {
                foundCount++
              }
            }
          })
          if (!foundCount) {
            throw new Error('该字段没有任何值包含原内容：'+value)
          }
          let count = selectedItems.length
          let id_list = selectedItems.map( ele => {
            let param = {
              id: ele.id,
            }
            if (ele[c.data.update_value_name]) {
              param[c.data.update_value_name] = ele[c.data.update_value_name].replace(value, dest_value)
            } else {
              param[c.data.update_value_name] = ''
            }
            post(options.module, options.method || 'update', param, options.config)
            .then(data => {
              if (count == 1) {
                self.amis.toast.success('成功')

                throw new Error('finish')
              }
              count--;
            })
            .catch(data => {
              count--;
              if (count == 0) {
                ret.crudComponent.handleQuery();
                ret.loadingComponent.setData(ret.loading_false)
                if (data+'' != 'Error: finish') {
                  self.amis.throw(data)
                }
                b({actionType: 'closeDialog',})
              }
            })
            return ele.id
          })
        }

        if (options && options.type == 'batchDelete') {
          fired = true
          if (ret.loading_name) {
            if (ret.loadingComponent.getData()[ret.loading_name]) {
              throw new Error('请稍后操作')
            }
            ret.loadingComponent.setData(ret.loading_true)
          }
          let selectedItems = ret.crudComponent.props.store.selectedItemsAsArray
          if (!selectedItems || !selectedItems.length) {
            throw new Error('请先选择需要替换内容的条目')
          }
          let count = selectedItems.length
          let id_list = selectedItems.map( ele => {
            post(options.module, options.method || 'delete', {id:[ele.id]}, options.config)
            .then(data => {
              if (count == 1) {
                self.amis.toast.success('成功')

                throw new Error('finish')
              }
              count--;
            })
            .catch(data => {
              count--;
              if (count == 0) {
                ret.crudComponent.handleQuery();
                ret.loadingComponent.setData(ret.loading_false)
                if (data+'' != 'Error: finish') {
                  self.amis.throw(data)
                }
              }
            })
            return ele.id
          })
        }

        if (options && options.type == 'delete') {
          fired = true
          if (ret.loading_name) {
            if (ret.loadingComponent.getData()[ret.loading_name]) {
              throw new Error('请稍后操作')
            }
            ret.loadingComponent.setData(ret.loading_true)
          }
          post(options.module, options.method || 'delete', {id:[c.data.id]}, options.config)
          .then(data => {
            self.amis.toast.success('成功')
            ret.crudComponent.handleQuery();
            ret.loadingComponent.setData(ret.loading_false)
          })
          .catch(data => {
            self.amis.throw(data)
          })
        }

        if (options && options.type == 'edit') {
          fired = true
          if (ret.loading_name) {
            if (ret.loadingComponent.getData()[ret.loading_name]) {
              throw new Error('请稍后操作')
            }
            ret.loadingComponent.setData(ret.loading_true)
          }

          let item = ret.crudComponent.props.data.items.find(ele => ele.id == c.data.id)
          if (!item) {
            throw new Error('未找到元素：'+c.data.id)
          }
          let diff = false
          ret.crudComponent.props.columns.forEach( ele => {
            if (item[ele.name] !== c.data[ele.name]) {
              diff = true
            }
          })
          if (!diff) {
            throw new Error('未改动任何数据')
          }
          let count = ret.selectedItems.length
          let id_list = ret.selectedItems.map( ele => {
            let item = {...c.data}
            if (options.prePost) {
              options.prePost(item)
            }
            item.id = ele.id
            post(options.module, options.method || 'update', item, options.config)
            .then(data => {
              if (count == 1) {
                self.amis.toast.success('成功')

                throw new Error('finish')
              }
              count--;
            })
            .catch(data => {
              count--;
              if (count == 0) {
                ret.crudComponent.handleQuery();
                ret.loadingComponent.setData(ret.loading_false)
                if (data+'' != 'Error: finish') {
                  self.amis.throw(data)
                } else {
                  ret.formComponent.handleAction({}, {
                    actionType:'confirm',
                  })
                }
              }
            })
            return ele.id
          })
        }
        if (options && options.type == 'custom') {
          fired = true
          
          if (ret.loading_name) {
            if (ret.loadingComponent.getData()[ret.loading_name]) {
              throw new Error('请稍后操作')
            }
            ret.loadingComponent.setData(ret.loading_true)
          }

          let count = ret.selectedItems.length
          let id_list = ret.selectedItems.map( ele => {
            let item = {...c.data}
            if (options.prePost) {
              options.prePost(item)
            }
            item.id = ele.id
            post(options.module, options.method || 'custom', item, options.config)
            .then(data => {
              if (count == 1) {
                self.amis.toast.success('成功')

                throw new Error('finish')
              }
              count--;
            })
            .catch(data => {
              count--;
              if (count == 0) {
                ret.crudComponent.handleQuery();
                ret.loadingComponent.setData(ret.loading_false)
                if (data+'' != 'Error: finish') {
                  self.amis.throw(data)
                }
              }
            })
            return ele.id
          })
        }

        if (options && !fired) {
          if (!options || !options.type) {
            throw new Error('miss action type')
          }
          throw new Error('invalid action type:'+options.type)
        }
      
      }catch(ex) {
        console.error(ex)
        if (ret.loading_name) {
          ret.loadingComponent.setData(ret.loading_false)
        }
        self.amis.toast.error(ex)
        throw ex
      }

      return ret;

    },
    
  }

  watch(self.amis.pageValue, (v,p) => {
    let e = self.amis.amisInstance.getComponentByName(self.amis.pageComponentId)
    if (e) {
      e.setData({v:v})
    }
  })

  self.initAmis = (dom, schema) => {
    //amis污染了window.MonacoEnvironment，需要删除，否则比对结果的背景颜色不正常
    delete window.MonacoEnvironment

    self.amis = {
      ...self.amis,
      ...amisRequire('amis'),
    }
    let amis = amisRequire('amis/embed');
    let axios = amisRequire('axios')
    
    self.amis.axios = axios
    const app = schema

    let findPage = function(e) {
      if (!e || typeof e === 'string'){
        return
      }
      if(e.type == 'page'){
        return e
      }
      for(let p in e){
        let ret = findPage(e[p])
        if(ret){
          return ret
        }
      }

    }
    let page = findPage(schema)
    if(!page ||!page.id) {
      if (!page) {
        throw new Error('cannot find page')
      }
      throw new Error('page miss prop: id')
    }
    self.amis.componentId = page.id


    setTimeout(() => {
      self.amis.amisInstance = amis.embed(dom,app,
        {
          self,
        },
        {
          // theme: 'ang',
          toastPosition: 'top-right',
          fetcher: (request) => {
            if (request.custom) {
              if (!request.custom.module) {
                throw new Error('miss config: custom.module')
              }
              if (request.custom.method) {
                return post(request.custom.module, request.custom.method, JSON.parse(request.data), {withConfig:true})
                .then(response => {
                  if (request.custom.method_total) {
                    return post(request.custom.module, request.custom.method_total, JSON.parse(request.data))
                    .then(more_data => {
                      response.data.total = more_data
                      return response
                    })
                  }
                })
              }
            }
            let {
              url, // 接口地址
              method, // 请求方法 get、post、put、delete
              data, // 请求数据
              responseType,
              config, // 其他配置
              headers // 请求头
            } = request;
            config = config || {};
            config.withCredentials = true;
            responseType && (config.responseType = responseType);

            if (config.cancelExecutor) {
              config.cancelToken = new (axios).CancelToken(
                config.cancelExecutor
              );
            }

            config.headers = headers || {};

            if (method !== 'post' && method !== 'put' && method !== 'patch') {
              if (data) {
                config.params = data;
              }

              return (axios)[method](url, config)
              
            } else if (data && data instanceof FormData) {
              config.headers = config.headers || {};
              config.headers['Content-Type'] = 'multipart/form-data';
            } else if (
              data &&
              typeof data !== 'string' &&
              !(data instanceof Blob) &&
              !(data instanceof ArrayBuffer)
            ) {
              data = JSON.stringify(data);
              config.headers = config.headers || {};
              config.headers['Content-Type'] = 'application/json';
            }

            return (axios)[method](url, data, config)
            .then(response => {
              if (config.more_post) {
                return config.more_post(url, response, config)
                .then( (more_data)=> {
                  return response;
                })
              }
      
              return response
            })
          },
          requestAdaptor(api) {
            return api;
          },

          responseAdaptor(api, payload, query, request, response) {
            return {
              data: {
                rows: payload.body,
                total:payload.total,
              },
              status: payload.code,
            };
            return payload;
          }
        })
      console.log('amis', self.amis)

      let setComponentIdCb = (timeout) => {
        setTimeout(() => {
          if (!self.amis.amisInstance.getComponentById
            && !self.amis.amisInstance.getComponentByName
            && !self.amis.amisInstance.getComponents
            )
          {
            setComponentIdCb()
            return;
          }
          self.amis.getComponentById = self.amis.amisInstance.getComponentById
          self.amis.getComponentByName = self.amis.amisInstance.getComponentByName
          self.amis.getComponents = self.amis.amisInstance.getComponents
          let componentInfos = self.amis.getComponentsInfo()
          if (!componentInfos) {
            console.error('setComponentIdCb 1')
            setComponentIdCb(1000)
            return;
          }
          let pageList = self.amis.getComponentListByType(componentInfos, 'page')
          if (!pageList || !pageList.length) {
            console.error('setComponentIdCb 2')
            setComponentIdCb(1000)
            return;
          }
          let pageComponent = self.amis.getObjectFirstPropValue(pageList[0]).component
          pageComponent.setData({
            title : unref(self.title),
          })
      }, timeout || 10)
      }
      setComponentIdCb()
    }, 1)
  }


  self.resetSortMenu = param => {
    console.log('resetSortMenu', param)
    let button = unref(self.handleSearchButton)
    button.showMenu = !button.showMenu
  }
  self.batchUpdateValueButton = ref({
    title:getStorageValue('batchUpdateValueButtonTitle') || '批量替换值(全部结果)',
    list: [
      {label:'批量替换值(全部结果)'},
      {label:'批量替换值(选中条目)'},
    ],
    loading:false,
    onclick: param => {
      let button = unref(self.batchUpdateValueButton)
      batchUpdateValue({param, self, selectOnly:button.title.indexOf('选中条目') >= 0})
    },
    oncommand: param => {
      let button = unref(self.batchUpdateValueButton)
      button.title = param
      setStorageValue('batchUpdateValueButtonTitle', button.title)
      button.onclick({...self, button})
    }
  })

  self.batchUpdateValueDialogInfo = ref({
    title: '批量替换值（全部结果）',
    visible:false,
    loading: false,
    rules:[],
    form:{},
    columns:[
      {
        prop: 'column_name',
        label: '字段',
        type: 'select',
        required: true,
        list: unref(self.columns).filter(ele => !(['id', 'workspace_name'].find(e => e == ele.prop))).map(ele => ({
          label: ele.prop + ' ' + ele.label,
          value: ele.prop,
        }))
      },
      {
        prop: 'value',
        label: '原值',
        required: true,
      },
      {
        prop: 'new_value',
        label: '新值',
      }
    ],
    onconfirm: (param) => {
      let {dialogInfo} = param
      if (!dialogInfo.form.column_name) {
        ElMessage.error('必须选择字段')
        return;
      }
      if (!dialogInfo.form.value) {
        ElMessage.error('必须输入原值')
        return;
      }
      let destValue = dialogInfo.form.new_value
      if (destValue === undefined || destValue === null) {
        destValue = ''
      }
      dialogInfo.loading = true
      self.handleSearch({
        pageNo: 1,
        pageSize: 10000,
        withoutSetData: true,
        // withoutProcessParam:  true,
      }).then(data => {
        if (dialogInfo.title.indexOf('选中条目') >= 0) {
          data = unref(self.selectRows)
        }
        let count = 0
        let module = unref(self.module)
        data.forEach(item => {
          let form = {id:item.id}
          let loop = 0
          let value = item[dialogInfo.form.column_name]
          if (value === undefined || value === null) {
            value = ''
          }
          while(loop < 100 && value.indexOf(dialogInfo.form.value) >= 0) {
            value = value.replace(dialogInfo.form.value, destValue)
          }
          form[dialogInfo.form.column_name] = value
          post(module, 'update', form)
          .then(() => {
            count++
            if (count == data.length) {
              dialogInfo.loading = false;
              dialogInfo.hide(param)
              self.handleSearch()
            }
          })
          .catch(ex => {
            console.error('ex', ex)
            dialogInfo.loading = false;
          })
        })
      })
    },
    hide: (param) => {
      const {dialogInfo} = param
      dialogInfo.form = {}
      dialogInfo.visible = false
      dialogInfo.loading = false
    },
    show: (param) => {
      let {dialogInfo, query, selectRows} = param

      dialogInfo.columns.forEach( item => {
        if (item.oninit) {
          item.oninit({...self, mode: 'init', dialogInfo:dialogInfo, column:item, columns: dialogInfo.columns, form: dialogInfo.form})
        }
      })

      dialogInfo.visible = true
    },
  })

  self.editDialogInfo = ref({
    title: ((self.editDialogInfo || ref({})).value || {}).title || '未知',
    visible:false,
    loading: false,
    rules:[],
    form:{},
    columns:[
      ...self.editColumns.value,
    ],
    edit2add: (param) => {
      const {dialogInfo, remoteConfig, getFormAndcheckRequired} = param
      dialogInfo.title = '添加';
      dialogInfo.form_ori = {}
    },
    onconfirm: (param) => {
      const {dialogInfo, remoteConfig, getFormAndcheckRequired} = param
      let remote;
      let newData = null;
      let needRefresh = unref(self.forceRefreshAfterUpdate);
      let form = getFormAndcheckRequired({form: dialogInfo.form, columns: dialogInfo.columns})
      if (!form) {
        return;
      }
      if ((dialogInfo.title || '').indexOf('编辑') >= 0) {
        newData = fixBlankFileds(dialogInfo.form, dialogInfo.form_ori, dialogInfo.columns)
        let newDataWithDiscard = fixBlankFileds(dialogInfo.form, dialogInfo.form_ori)
        if (!newData) {
          console.error('form', dialogInfo.form)
          console.error('form_ori', dialogInfo.form_ori)
          ElMessage.error(`未改动任何值`);
          return;
        }
        for(let item in dialogInfo.columns) {
          item = dialogInfo.columns[item]
          if (newDataWithDiscard[item.prop] !== null && newDataWithDiscard[item.prop] !== undefined) {
            if(item.refresh || item.discard) {
              needRefresh = true
            }
          }
        }
        remote = remoteConfig.edit
        if (!remote.keys || remote.keys.length == 0) {
          ElMessage.error(`未配置keys:${remote}`);
          return;
        }
        form = {...newData}
        if (form.query_options_setnull) {
          if (!('query_options' in form)) {
            form.query_options = {}
          }
          form.query_options.setnull = form.query_options_setnull
          delete form.query_options_setnull
        }
        for(let p in form) {
          let c = dialogInfo.columns.find(ele => ele.prop == p)
          if (c && form[p] === '' && c.empty_as_setnull) {
            if (!('query_options' in form)) {
              form.query_options = {}
            }
            if (!('setnull' in form.query_options)) {
              form.query_options.setnull = {}
            }
            form.query_options.setnull[p] = '';
            delete form[p]
          }
        }
        remote.keys.forEach(key => {
          form[key] = dialogInfo.form_ori[key]
        })
      } else {
        remote = remoteConfig.add
        needRefresh = true
        self.discardCount.value = false
      }
      dialogInfo.loading = true
      return post(remote.module, remote.method, form)
      .then( data => {
        if (data) {
          ElMessage.success(`修改成功`);
          return self.handleSearch({forceCount:true})
          .finally(() => {
            if (self.ShowAfterConfirm !== true) {
              dialogInfo.visible = false;
            }
            dialogInfo.loading = false
            if (self.custom.saveEditAfter) {
              self.custom.saveEditAfter({form, self})
            }
          })
        } else {
          ElMessage.error(`失败:${data}`);
          dialogInfo.loading = false
        }
      })
      .catch(err => {
        ElMessage.error(`失败:${err}`, err);
        dialogInfo.loading = false
      })
    },
    show: (param) => {
      const {dialogInfo, query, title} = param
      dialogInfo.title = title

      self.init_remote_list(self.editColumns.value, param)

      if (title == '编辑') {
        const selectRowData = getOnlySelectRowData(self.selectRows.value)
        if (!selectRowData) {
          return;
        }
        dialogInfo.form = {...selectRowData}
        dialogInfo.form_ori = self.selectRows.value[0]
        dialogInfo.columns.forEach( item => {
          if (item.type == 'upload') {
            try {
              let childNodes = document.getElementsByClassName('el-upload-list')[0].childNodes
              let childNodesCount = childNodes.length
              for(let childIndex = childNodesCount - 1; childIndex >= 0; childIndex--) {
                childNodes[childIndex].remove()
              }
            }catch(ex) {

            }

          }
          if (item.oninit) {
            let cb = item.oninit
            if (typeof(cb) == 'string') {
              cb = (dialogInfo.columns.find( item2 => item2.prop == cb) || {}).oninit
            }
            if(cb) {
              cb({...self, mode: 'init_dialog', form: dialogInfo.form, column: item, columns: dialogInfo.columns})
            }
          }
        })
        dialogInfo.columns.forEach( item => {
          if (item.onchange && dialogInfo.form[item.prop]) {
            let cb = item.onchange
            if (typeof(cb) == 'string') {
              cb = (dialogInfo.columns.find( item2 => item2.prop == cb) || {}).onchange
            }
            if(cb) {
              cb({...self, mode: 'init_dialog', form: dialogInfo.form, column: item, columns: dialogInfo.columns})
            }
          }
        })
      } else {
        dialogInfo.form = {}
        dialogInfo.form_ori = {}
        if (query.workspace_name) {
          let column = unref(self.editColumns).find(ele => ele.prop == 'workspace_name')
          if (column && column.hide !== true) {
            dialogInfo.form.workspace_name = query.workspace_name
          }
        }
        dialogInfo.columns.forEach( item => {
          if (item.oninit) {
            let cb = item.oninit
            if (typeof(cb) == 'string') {
              cb = (dialogInfo.columns.find( item2 => item2.prop == cb) || {}).oninit
            }
            if(cb) {
              cb({...self, mode: 'init_dialog', form: dialogInfo.form, column: item, columns: dialogInfo.columns})
            }
          }
        })
        dialogInfo.columns.forEach( item => {
          if (item.onchange && dialogInfo.form[item.prop]) {
            let cb = item.onchange
            if (typeof(cb) == 'string') {
              cb = (dialogInfo.columns.find( item2 => item2.prop == cb) || {}).onchange
            }
            if(cb) {
              cb({...self, mode: 'init_dialog', form: dialogInfo.form, column: item, columns: dialogInfo.columns})
            }
          }
        })
      }
      
      dialogInfo.visible = true
    },
    hide: (param) => {
      const {dialogInfo} = param
      dialogInfo.visible = false
      dialogInfo.loading = false
    },
  })

  self.columns.value.forEach( item => {
    if (item.required) {
      let obj = {}
      obj[item.prop] = { required: true, trigger: 'blur', message: '请输入'+item.label },
      self.form_rules.value.push(obj)
    }
  })

  self.queryColumns.value.forEach( item => {
    if (!item.label) {
      let col = unref(self.columns).find(ele => ele.prop == item.prop)
      if (col) {
        item.label = col.label
      }
    }
  })

  self.queryColumns.value.forEach( item => {
    if (item.oninit) {
      item.oninit({...self, mode: 'init', form: self.query.value, column: item, columns: self.queryColumns.value})
    }
  })

  self.queryColumns.value.forEach( item => {
    if (self.query.value[item.prop] && item.onchange) {
      item.onchange({...self, mode: 'init', form: self.query.value, column: item, columns: self.queryColumns.value})
    }
  })

  self.onChange = onChange

  self.onFocus = onFocus

  self.onMounted = (v) => {
    if (v) {
      for(let p in v) {
        self[p].value = v[p].value;
      }
    }
    self.sortMethod();
    if (self.refresh_oninit !== false) {
      self.handleSearch();
    }
    if (self.custom.onMounted) {
      self.custom.onMounted();
    }
  }

  if (self.custom && self.custom.onInit) {
    self.custom.onInit();
  }

}